package cn.myframe.utils.aop;

import cn.myframe.db.datascope.DataScope;
import cn.myframe.db.datascope.annotation.DataScopeAnno;
import cn.myframe.db.datascope.annotation.DataScopeIgnore;
import cn.myframe.entity.bus.BusCompanyEntity;
import cn.myframe.service.bus.BusCompanyService;
import cn.myframe.service.sys.SysRoleCompanyService;
import cn.myframe.service.sys.SysRoleService;
import cn.myframe.service.sys.SysUserRoleService;
import cn.myframe.service.sys.SysUserService;
import cn.myframe.shiro.ShiroUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.*;

/**
 * 数据权限切面
 * 
 * @author ynz
 * @email ynz@myframe.cn
 * @date 2018年8月7日 下午4:40:15
 */
@Aspect
@Component
public class DataScopeAspect {
	
	@Autowired
	private SysUserService sysUserService;
	@Autowired
	private SysUserRoleService sysUserRoleService;
	@Autowired
	private SysRoleCompanyService sysRoleCompanyService;
	@Autowired
	private BusCompanyService busCompanyService;
	@Autowired
	private SysRoleService sysRoleService;
	

	@Pointcut("@annotation(cn.myframe.db.datascope.annotation.DataScopeAnno)")
	public void pointCut() { 
		
	}

	@Pointcut("execution(* cn.myframe.controller..*.list(..))")
	public void pointCutList() {}
	@Pointcut("execution(* cn.myframe.controller..*.lists(..))")
	public void pointCutLists() {}
	
	@Before("pointCut() || pointCutList() || pointCutLists()")
	public void saveSysLog(JoinPoint joinPoint) {
		if (ShiroUtils.getUserEntity().getUserId() == 1) {
			return;
		}
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		Method method = signature.getMethod();
		DataScopeIgnore dataScopeIgnore = method.getAnnotation(DataScopeIgnore.class);
		if (dataScopeIgnore != null) {
			return;
		}
		RequiresPermissions requiresPermissions = method.getAnnotation(RequiresPermissions.class);
		String[] perms = requiresPermissions.value();
		String listPerm = null;
		if (perms != null && perms.length > 0) {
			listPerm = perms[0];
		} else {
			return;
		}
		DataScopeAnno dataScopeAnno = method.getAnnotation(DataScopeAnno.class);
		String dataScopeValue = "0";
		String dataScopeName = "CREATE_BY";
		if (dataScopeAnno != null) {
			dataScopeValue = dataScopeAnno.value();
			dataScopeName = dataScopeAnno.scopeName();
		}
		//请求的参数
		Object[] args = joinPoint.getArgs();
		if(args != null && args.length > 0){
			Object obj = args[0];
			if (obj instanceof Map) {
				List<Long> userIds = null;
				DataScope dataScope = null;
				Long companyNo = null;
				List<BusCompanyEntity> offSpring = null;
				List<Long> companyNoList = null;
				switch(dataScopeValue){
					case "0" :
						List<Long> roleIdList = sysUserRoleService.selectUserRoleIds(ShiroUtils.getUserEntity().getUserId());
						if (roleIdList == null || roleIdList.size() == 0) {
							((Map) obj).put("dataScope", new DataScope(dataScopeName, Arrays.asList(-1L)));
							break;
						}
						for (int i = 0; i < roleIdList.size(); i++) {
							Boolean res = sysRoleService.hasPerm(roleIdList.get(i), listPerm);
							if (!res) {
								roleIdList.remove(i);
							}
						}
						Set<Long> relCompanyIds = sysRoleCompanyService.findCompanyIdsByRoleIds(roleIdList);
						userIds = sysUserService.selectIdsByCompanyIds(relCompanyIds);
						dataScope = new DataScope(dataScopeName, userIds);
						((Map) obj).put("dataScope", dataScope);
						break;
					case "1" :
						companyNo = ShiroUtils.getUserEntity().getCompanyNo();
						if (companyNo == null) {
							((Map) obj).put("dataScope", new DataScope(dataScopeName, Arrays.asList(-1L)));
							break;
						}
						userIds = sysUserService.selectIdsByCompanyIds(Arrays.asList(companyNo));
						dataScope = new DataScope(dataScopeName, userIds);
						((Map) obj).put("dataScope", dataScope);
						break;
					case "2" :
						companyNo = ShiroUtils.getUserEntity().getCompanyNo();
						if (companyNo == null) {
							((Map) obj).put("dataScope", new DataScope(dataScopeName, Arrays.asList(-1L)));
							break;
						}
						companyNoList = new ArrayList<>();
						companyNoList.add(companyNo);
						offSpring = busCompanyService.findOffSpring(companyNo);
						if (offSpring != null && offSpring.size() > 0) {
							for (int i = 0; i < offSpring.size(); i++) {
								companyNoList.add(offSpring.get(i).getCompanyNo());
							}
						}
						userIds = sysUserService.selectIdsByCompanyIds(companyNoList);
						dataScope = new DataScope(dataScopeName, userIds);
						((Map) obj).put("dataScope", dataScope);
						break;
					case "3" :
						companyNo = ShiroUtils.getUserEntity().getCompanyNo();
						if (companyNo != null) {
							offSpring = busCompanyService.findOffSpring(companyNo);
							if (offSpring != null && offSpring.size() > 0) {
								companyNoList = new ArrayList<>();
								for (int i = 0; i < offSpring.size(); i++) {
									companyNoList.add(offSpring.get(i).getCompanyNo());
								}
							}
						}
						if (companyNoList != null) {
							userIds = sysUserService.selectIdsByCompanyIds(companyNoList);
							userIds.add(ShiroUtils.getUserEntity().getUserId());
							dataScope = new DataScope(dataScopeName, userIds);
						} else {
							dataScope = new DataScope(dataScopeName, Arrays.asList(ShiroUtils.getUserEntity().getUserId()));
						}
						((Map) obj).put("dataScope", dataScope);
						break;
					case "4" :
						dataScope = new DataScope(dataScopeName, Arrays.asList(ShiroUtils.getUserEntity().getUserId()));
						((Map) obj).put("dataScope", dataScope);
						break;
					default:break;

				}


			}
		}
	}
	
	
}
